#include "libglew/glew.h"
#ifdef __APPLE__
#include <GLUT/glut.h>
#endif
#ifdef WIN32
#include <GL/glut.h>
#endif
#include <sstream>
#include <vector>
#include "Program.h"

using namespace lib3dw;
using namespace Dicewars;

Program* program;
static void Render(){ program->Render(); }
static void ResizeWindow(int x, int y){ program->ResizeWindow(x, y); }
static void HandleKeyPresses(unsigned char key, int x, int y){ program->HandleKeyPresses(key, x, y); }
static void HandleSpecialKeyPresses(int key, int x, int y){ program->HandleSpecialKeyPresses(key, x, y); }
static void HandleKeyReleases(unsigned char key, int x, int y){ program->HandleKeyReleases(key, x, y); }
static void HandleMouseClicks(int button, int state, int x, int y){ program->HandleMouseClicks(button, state, x, y); }
static void HandleActiveMouseMotion(int x, int y){ program->HandleActiveMouseMotion(x, y); }
static void HandlePassiveMouseMotion(int x, int y){ program->HandlePassiveMouseMotion(x, y); }
static void UpdateGameState(){ program->UpdateGameState(); }

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	std::string width = "640";
	std::string height = "480";
	std::string depth;
	std::string refresh;
	switch(argc)
	{	
		case 6:
		{
			std::string renderMode = std::string(argv[5]);
			if (renderMode == "ImmediateMode"){ ConfigSingleton::Instance()->SetRenderMode(RenderImmediate);}
			else if(renderMode =="DisplayList"){ ConfigSingleton::Instance()->SetRenderMode(RenderDisplayList);}
			else{ConfigSingleton::Instance()->SetRenderMode(RenderVBO);}
		}
		case 5:
		{
			depth = std::string(argv[3]);
			refresh = std::string(argv[4]);
			std::string mode = width + "x" + height + ":" + depth + "@" + refresh;
			glutGameModeString(mode.c_str());
			glutEnterGameMode();
			break;
		}
		case 4:
			{
				std::string renderMode = std::string(argv[3]);
				if (renderMode =="ImmediateMode"){ ConfigSingleton::Instance()->SetRenderMode(RenderImmediate);}
				else if(renderMode =="DisplayList"){ ConfigSingleton::Instance()->SetRenderMode(RenderDisplayList);}
				else{ConfigSingleton::Instance()->SetRenderMode(RenderVBO);}
			}
		case 3:
		{
			width = std::string(argv[1]);
			height = std::string(argv[2]);
		}
		default:
		{
			glutInitWindowPosition(100, 100);
			std::istringstream heightStream(width);
			std::istringstream widthStream(height);
			int iwidth;
			int iheight;
			heightStream >>iwidth;
			widthStream >> iheight;
			glutInitWindowSize(iwidth, iheight);
			glutCreateWindow("3Dicewars");
		}
	}
	program = new Program();
	glutIgnoreKeyRepeat(true); 
    glutDisplayFunc(Render);
	glutReshapeFunc(ResizeWindow);
	glutKeyboardFunc(HandleKeyPresses);
	glutSpecialFunc(HandleSpecialKeyPresses);
	glutKeyboardUpFunc(HandleKeyReleases);
	glutMouseFunc(HandleMouseClicks);
	glutMotionFunc(HandleActiveMouseMotion);
	glutPassiveMotionFunc(HandlePassiveMouseMotion);
	glutIdleFunc(UpdateGameState);
	// init glew before we setup our scene because otherwise shader loading will fail
	glewInit();
	program->Init();
    glutMainLoop();
	delete program;
	return 0;
}